package com.geektime.hello.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class AspectDemo {

    private Logger logger = LoggerFactory.getLogger(AspectDemo.class);

    @Autowired
    private HttpServletRequest request;

    @Pointcut("execution(* com.geektime.hello.controller.*.*(..))")
    private void aspect() {
    }

    @Before("aspect()")
    public void before(JoinPoint joinPoint) {
        logger.info("===============================Start========================");
        logger.info("IP                 : {}", request.getRemoteAddr());
        logger.info("URL                : {}", request.getRequestURL().toString());
        logger.info("HTTP Method        : {}", request.getMethod());
        logger.info("Class Method       : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
    }

    @Around("aspect()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        logger.info("Request Params     : {}", getRequestParams(joinPoint));
        logger.info("Result             : {}", result);
        logger.info("Time Cost          : {} ms", System.currentTimeMillis() - start);
        return result;
    }

    @After("aspect()")
    public void after() {
        logger.info("===============================End========================");
    }

    /**
     * 获取入参
     *
     * @param joinPoint
     * @return
     */
    private Map<String, Object> getRequestParams(ProceedingJoinPoint joinPoint) {
        Map<String, Object> requestParams = new HashMap<>();
        //参数名
        String[] paramNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        Object[] paramValues = joinPoint.getArgs();

        for (int i = 0; i < paramNames.length; i++) {
            Object value = paramValues[i];
            if (value instanceof MultipartFile) {
                MultipartFile file = (MultipartFile) value;
                value = file.getOriginalFilename();
            }
            requestParams.put(paramNames[i], value);
        }
        return requestParams;
    }
}
